package com.telenav.snowsweeper.data;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

import com.telenav.snowsweeper.renderer.Util;

import android.graphics.Rect;

public class EdgeMap {
	private Edge[][] verticalEdges;			// 6 * 9
	private Edge[][] horizontalEdges;		// 7 * 8
	private HashMap<String, Edge> mapEdges = new HashMap<String, Edge>();
	public EdgeMap(int[][] vPosTransTimes, int[][] vNegTransTimes, int[][] hPosTransTimes, int[][] hNegTransTimes) throws InitException {
		try {
			verticalEdges = new Edge[vPosTransTimes.length][];
			for (int i = 0; i < vPosTransTimes.length; ++i) {
				verticalEdges[i] = new Edge[vPosTransTimes[i].length];
				for (int j = 0; j < vPosTransTimes[i].length; ++j) {
					if (vPosTransTimes[i][j] > 0 || vNegTransTimes[i][j] > 0) {
						verticalEdges[i][j] = new Edge("" + (i << 24 | j << 16), (i << 24 | j << 16), vPosTransTimes[i][j], vNegTransTimes[i][j], 
								PointsManager.getPoint(i, j), PointsManager.getPoint(i + 1, j));
					}
				}
			}
			
			horizontalEdges = new Edge[hPosTransTimes.length][];
			for (int i = 0; i < hPosTransTimes.length; ++i) {
				horizontalEdges[i] = new Edge[hPosTransTimes[i].length];
				for (int j = 0; j < hPosTransTimes[i].length; ++j) {
					if (hPosTransTimes[i][j] > 0 || hNegTransTimes[i][j] > 0)
						horizontalEdges[i][j] = new Edge("" + (i << 8 | j), (i << 8 | j), hPosTransTimes[i][j], hNegTransTimes[i][j],
								PointsManager.getPoint(i, j), PointsManager.getPoint(i, j + 1));
				}
			}
		}
		catch (Exception e) {
			throw new InitException();
		}
	}
	
    public EdgeMap(Vector<Edge> edges)
    {
        if (edges != null)
        {
            Iterator<Edge> it = edges.iterator();
            Edge e;
            int[][] vPosTransTimes = new int[6][9];
            int[][] vNegTransTimes = new int[6][9];
            String[][] vEdgeIndex = new String[6][9];
            int[][] hPosTransTimes = new int[7][8];
            int[][] hNegTransTimes = new int[7][8];
            String[][] hEdgeIndex = new String[7][8];
            for (; it.hasNext();)
            {
                e =it.next();
                mapEdges.put(e.getIndex(), e);
                // convert to render data
                int x1 = e.getBegin().getColumn();
                int x2 = e.getEnd().getColumn();
                int y1 = e.getBegin().getRow();
                int y2 = e.getEnd().getRow();
                int indexX;
                int indexY;
                if (x1 == x2)
                {
                    indexX = x1;
                    indexY = y1 > y2 ? y2 : y1;
                    vPosTransTimes[indexY][indexX] = e.getPosTransTime();
                    vNegTransTimes[indexY][indexX] = e.getNegTransTime();
                    vEdgeIndex[indexY][indexX] = e.getIndex();
                } else if (y1 == y2)
                {
                    indexX = x1 > x2 ? x2 : x1;
                    indexY = y1;
                    hPosTransTimes[indexY][indexX] = e.getPosTransTime();
                    hNegTransTimes[indexY][indexX] = e.getNegTransTime();
                    hEdgeIndex[indexY][indexX] = e.getIndex();
                }
            }
            try {
                verticalEdges = new Edge[vPosTransTimes.length][vPosTransTimes[0].length];
                for (int i = 0; i < vPosTransTimes.length; ++i) {
                    for (int j = 0; j < vPosTransTimes[i].length; ++j) {
                        if (vPosTransTimes[i][j] > 0 || vNegTransTimes[i][j] > 0) {
                            verticalEdges[i][j] = new Edge(vEdgeIndex[i][j], i << 24 | j << 16, vPosTransTimes[i][j], vNegTransTimes[i][j], 
                                    PointsManager.getPoint(i, j), PointsManager.getPoint(i + 1, j));
                        }
                    }
                }
                
                horizontalEdges = new Edge[hPosTransTimes.length][hPosTransTimes[0].length];
                for (int i = 0; i < hPosTransTimes.length; ++i) {
                    for (int j = 0; j < hPosTransTimes[i].length; ++j) {
                        if (hPosTransTimes[i][j] > 0 || hNegTransTimes[i][j] > 0)
                            horizontalEdges[i][j] = new Edge(hEdgeIndex[i][j], i << 8 | j, hPosTransTimes[i][j], hNegTransTimes[i][j],
                                    PointsManager.getPoint(i, j), PointsManager.getPoint(i, j + 1));
                    }
                }
            }
            catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    }

	public Edge getHorEdge(int row, int col) {	    
		if (row < horizontalEdges.length && col < horizontalEdges[row].length) {
			return horizontalEdges[row][col];
		}
		return null;
	}
	
	public Edge getVertEdge(int row, int col) {
		if (row < verticalEdges.length && col < verticalEdges[row].length) {
			return verticalEdges[row][col];
		}
		return null;
	}
	
	public void clipEdges(Rect clip, Vector<Edge> collection) {
		/*int left = Util.x2TileColumn(clip.left);
		int right = Util.x2TileColumn(clip.right);
		int top = Util.y2TileRow(clip.top);
		int bottom = Util.y2TileRow(clip.bottom);
		
		int temp = right + 1;
		for (int i = top; i <= bottom; ++i) {
			for (int j = left; j <= temp; ++j) {
				if (verticalEdges[i][j] != null)
					collection.add(verticalEdges[i][j]);
			}
		}
		
		temp = bottom + 1;
		for (int i = top; i <= temp; ++i) {
			for (int j = left; j <= right; ++j) {
				if (horizontalEdges[i][j] != null)
					collection.add(horizontalEdges[i][j]);
			}
		}*/
		for (int i = 0; i < Util.ROW; ++i) {
			for (int j = 0; j <= Util.COLUMN; ++j) {
				if (verticalEdges[i][j] != null)
					collection.add(verticalEdges[i][j]);
			}
		}
		for (int i = 0; i <= Util.ROW; ++i) {
			for (int j = 0; j < Util.COLUMN; ++j) {
				collection.add(horizontalEdges[i][j]);
			}
		}
	}
	
	public class InitException extends Exception {
		private static final long serialVersionUID = 1L;
	}
	
	public int[] getVEdgeSize() {
		if (verticalEdges == null || verticalEdges.length == 0)
			return null;
		return new int[]{ verticalEdges.length, verticalEdges[0].length };
	}
	
	public int[] getHEdgesSize() {
		if (horizontalEdges == null || horizontalEdges.length == 0)
			return null;
		return new int[]{ horizontalEdges.length, horizontalEdges[0].length };
	}
	
	public Edge getEdgeByPoints(Point point1, Point point2) {
		if (!Util.isPointsClosed(point1, point2))
			return null;
		
		if (point1.getRow() == point2.getRow()) {
			return getHorEdge(point1.getRow(), Math.min(point1.getColumn(), point2.getColumn()));
		}
		else {
			return getVertEdge(Math.min(point1.getRow(), point2.getRow()), point1.getColumn());
		}
	}
	
	public Edge getEdgeByID(String id)
	{
	  return this.mapEdges.get(id);
	}
}
